package com.erp.framework.util;

import java.math.BigDecimal;

import com.erp.framework.SimpleConstants;
import com.erp.framework.util.logger.Logger;

public class NumberUtil implements SimpleConstants{
	/**
	 * Round a double to the given places.
	 * @param val - the value to be rounded
	 * @param places
	 * @return	a double
	 */	public static double roundDouble(double val, int places) {
		long factor = (long)Math.pow(10,places);

		// Shift the decimal the correct number of places to the right.
		val = val * factor;

		// Round to the nearest integer.
		long tmp = Math.round(val);

		// Shift the decimal the correct number of places back to the left.
		double rslt = (double)tmp / factor;
		return rslt;
	}

	/**
	 * @param num
	 * @param size
	 * @param mask
	 * @return
	 */
	 /*
	public static String lpad(int num, int size, String mask){
			return lpad(new BigDecimal(new Integer(num).toString()), size, mask);
	}
*/
	/**
	 * @param num
	 * @param size
	 * @param mask
	 * @return
	 */
	public static String lpad(BigDecimal num, int size, String mask){
		String result = "";

		if(num == null){
			Logger.warn("lpad(), Input number is null.");
			return "";
		}

		if(size == 0){
			Logger.warn("lpad(), Input size is 0.");
			return "";
		}

		if(mask == null){
			Logger.warn("lpad(), Input mask is null.");
			return "";
		}

		String tmp = String.valueOf(num);
		int numToFill = size-tmp.length();
		for(int i = 0; i < numToFill; i++){
			result = mask + result;
		}
		result = result + tmp;

		return result;
	}


	/**
	 * @param num
	 * @param size
	 * @param mask
	 * @return
	 */
	public static String rpad(BigDecimal num, int size, String mask){
		String result = "";

		if(num == null){
			Logger.warn("rpad(), Input number is null.");
			return "";
		}

		if(size == 0){
			Logger.warn("rpad(), Input size is 0.");
			return "";
		}

		if(mask == null){
			Logger.warn("rpad(), Input mask is null.");
			return "";
		}

		String tmp = String.valueOf(num);
		int numToFill = size-tmp.length();
		for(int i = 0; i < numToFill; i++){
			result = mask + result;
		}
		result = tmp + result;

		return result;
	}

	/**
	 * @param num
	 * @param size
	 * @param mask
	 * @return
	 */
	/*
	public static String rpad(int num, int size, String mask){
		return lpad(new BigDecimal(new Integer(num).toString()), size, mask);
	}
	*/

	/**
	 * Return true if the number is zero or empty.
	 * @param bd - the BigDecimal to be tested.
	 * @return	true if the number is zero or empty, false otherwise.
	 */
	public static boolean numberIsZeroOrEmpty(BigDecimal bd){
		if(bd == null || SimpleConstants.BIGDECIMAL_ZERO.equals(bd))
			return true;
		return false;
	}



	/**
	 * Return true if the string contains only number.
	 * @param value - the string to be tested.
	 * @return	true if the string contains only number, false otherwise.
	 */
	public static boolean isValidNumber(String value) {
		try {
			double d = Double.parseDouble(value);
			return true;
		} catch (Exception e) {
//			Logger.logExceptions("isValidNumber()", e);
			return false;
		}
	}

	/**
	 * Return true if the string contains only number and it is greater than/greater than and
	 * equals to a number.
	 * @param value - the string to be tested.
	 * @param minValue	- a min value.
	 * @param inclusive	- if test for "greater than and equal", it should be setted to true, false otherwise.
	 * @return	true if the string contains only number and it is greater than/greater than and
	 * equals to a number, false otherwise.
	 */
	public static boolean isValidNumber(String value, double minValue, boolean inclusive) {
		try {
			double d = Double.parseDouble(value);
			return (inclusive) ? (d >= minValue) : (d > minValue);
		}
		catch (Exception e) {
//			Logger.logExceptions("isValidNumber()", e);
			return false;
		}
	}


	/**
	 * Return true if the string contains only number and it is greater than/greater than and
	 * equals to a number.
	 * @param value - the string to be tested.
	 * @param minValue	- a min value.
	 * @param inclusive	- if test for "greater than and equal", it should be setted to true, false otherwise.
	 * @param length	- .
	 * @param precision	- .
	 * @return	true if the string contains only number and it is greater than/greater than and
	 * equals to a number, false otherwise.
	 */
	public static boolean isValidNumber(String value, double minValue, boolean inclusive, int length, int precision) {
		try {
			if(!isValidNumber(value, length, precision)){
				return false;
			}

			double d = Double.parseDouble(value);
			return (inclusive) ? (d >= minValue) : (d > minValue);
		}
		catch (Exception e) {
//			Logger.logExceptions("isValidNumber()", e);
			return false;
		}
	}

	/**
	 * Return true if the string contains only number
	 * @param str - the string to be tested.
	 * @param length	- .
	 * @param precision	- .
	 * @return	true if the string contains only number, false otherwise.
	 */
	public static boolean isValidNumber(String str, int length, int precision) {
		if(str==null)
			return false;

		try {
			BigDecimal d = new BigDecimal(str);
			return isValidNumber(d, length, precision);
		}
		catch (Exception e) {
//			Logger.logExceptions("isValidNumber()", e);
			return false;
		}
	}


	/**
	 * Return true if the number is valid
	 * @param num - the string to be tested.
	 * @param length	- .
	 * @param precision	- .
	 * @return	true if the number is valid, false otherwise.
	 */
	public static boolean isValidNumber(Number num, int length, int precision) {
		if (num == null) {
//			Logger.warn("isValidNumber(), input number is null");
			return false;
		}

		try {
			String str = num.toString();

			int lengthOfStr = str.length();
			int dp = str.indexOf(".");
			int integralPartLength = 0;
			int fractionalPartLength = 0;

			if (dp != -1) {
				integralPartLength = dp;
				fractionalPartLength = lengthOfStr - dp -1;
			}
			else {
				integralPartLength = lengthOfStr;
			}

			if (fractionalPartLength > precision ||
				integralPartLength > length - precision) {
				return false;
			}
		}
		catch (Exception e) {
//			Logger.logExceptions("isValidNumber()", e);
			return false;
		}

		return true;
	}

	/**
	 * Return true if the string is a valid number.
	 * @param value	- the string to be tested.
	 * @param minValue	- the min value
	 * @param maxValue	- the max value
	 * @param inclusive	- if test for "greater than and equal" and "smaller than and equal", it should be setted to true, false otherwise.
	 * @return
	 */
	public static boolean isValidNumber(String value, double minValue, double maxValue, boolean inclusive) {
		try {
			double d = Double.parseDouble(value);
			return (inclusive) ? (d >= minValue && d <= maxValue) : (d > minValue && d < maxValue);
		}
		catch (Exception e) {
//			Logger.logExceptions("isValidNumber()", e);
			return false;
		}
	}

	/**
	 * Return true if the string is a valid number.
	 * @param value	- the string to be tested.
	 * @param minValue	- the min value
	 * @param maxValue	- the max value
	 * @param inclusive	- if test for "greater than and equal" and "smaller than and equal", it should be setted to true, false otherwise.
	 * @return
	 */
	public static boolean isValidNumber(String value, double minMaxValue, String minMaxFlag, boolean inclusive) {
		try {
			double d = Double.parseDouble(value);
			
			if(SimpleConstants.MIN_FLAG.equals(minMaxFlag)){
				return (inclusive) ? (d >= minMaxValue) : (d > minMaxValue);
			} else {
				return (inclusive) ? (d <= minMaxValue) : (d < minMaxValue);
			}
		}
		catch (Exception e) {
//			Logger.logExceptions("isValidNumber()", e);
			return false;
		}
	}
	
	/**
	 * @param value
	 * @return
	 */
	public static boolean isValidPositiveInteger(String value) {
		try {
			int i = Integer.parseInt(value);

			if(i <= 0){
				return false;
			}

			return true;
		} catch (Exception e) {
//			Logger.logExceptions("isValidPositiveInteger()", e);
			return false;
		}
	}

	public static boolean isValidInteger(String value) {
		try {
			int i = Integer.parseInt(value);
			return true;
		} catch (Exception e) {
//			Logger.logExceptions("isValidInteger()", e);
			return false;
		}
	}

	public static boolean isValidInteger(String value, int minValue, boolean inclusive) {
		try {
			int i = Integer.parseInt(value);
			return (inclusive) ? (i >= minValue) : (i > minValue);
		} catch (Exception e) {
//			Logger.logExceptions("isValidInteger()", e);
			return false;
		}
	}

	public static boolean isValidInteger(String value, int minMaxValue, String minMaxFlag, boolean inclusive) {
		try {
			int i = Integer.parseInt(value);
			
			if(SimpleConstants.MIN_FLAG.equals(minMaxFlag)){
				return (inclusive) ? (i >= minMaxValue) : (i > minMaxValue);
			} else {
				return (inclusive) ? (i <= minMaxValue) : (i < minMaxValue);
			}
		} catch (Exception e) {
//			Logger.logExceptions("isValidInteger()", e);
			return false;
		}
	}	

	public static boolean isValidInteger(String value, int minValue, int maxValue, boolean inclusive) {
		try {
			int i = Integer.parseInt(value);
			return (inclusive) ? (i >= minValue && i <= maxValue) : (i > minValue && i < maxValue);
		} catch (Exception e) {
//			Logger.logExceptions("isValidInteger()", e);
			return false;
		}
	}

	public static boolean isValidNonNegativeInteger(String value) {
		try {
			int i = Integer.parseInt(value);

			if(i < 0){
				return false;
			}

			return true;
		} catch (Exception e) {
//			Logger.logExceptions("isValidNonNegativeInteger()", e);
			return false;
		}
	}

	public static boolean isValidPositiveDecimal(String str, int length, int precision){
		if(!isValidNumber(str, length, precision)){
			return false;
		}
		try {
			double d = Double.parseDouble(str);
			if(d > 0) {
				return true;
			} else {
				return false;
			}
		}
		catch (Exception e) {
//			Logger.logExceptions("isValidPositiveDecimal()", e);
			return false;
		}
	}

	public static boolean isValidPositiveDecimal(String value) {
		try {
			double d = Double.parseDouble(value);
			if(d > 0) {
				return true;
			} else {
				return false;
			}
		} catch (Exception e) {
//			Logger.logExceptions("isValidPositiveDecimal()", e);
			return false;
		}
	}
	public static boolean isValidNonNegativeDecimal(String str, int length, int precision){
		if(!isValidNumber(str, length, precision)){
			return false;
		}
		try {
			double d = Double.parseDouble(str);
			if(d < 0) {
				return false;
			} else {
				return true;
			}
		}
		catch (Exception e) {
//			Logger.logExceptions("isValidNonNegativeDecimal()", e);
			return false;
		}
	}

	public static boolean isValidNonNegativeDecimal(String value) {
		try {
			double d = Double.parseDouble(value);
			if(d < 0) {
				return false;
			} else {
				return true;
			}
		} catch (Exception e) {
//			Logger.logExceptions("isValidNonNegativeDecimal()", e);
			return false;
		}
	}

	public static boolean isValidPositiveLongInteger(String value) {
		try {
			long i = Long.parseLong(value);

			if(i <= 0){
				return false;
			}

			return true;
		} catch (Exception e) {
//			Logger.logExceptions("isValidPositiveLongInteger()", e);
			return false;
		}
	}

	public static boolean isValidLongInteger(String value) {
		try {
			long i = Long.parseLong(value);

			return true;
		} catch (Exception e) {
//			Logger.logExceptions("isValidPositiveLongInteger()", e);
			return false;
		}
	}

	public static boolean isValidNonNegativeLongInteger(String value) {
		try {
			long l = Long.parseLong(value);

			if (l < 0) {
				return false;
			}
		} catch (Exception e) {
//			Logger.logExceptions("isValidNonNegativeLongInteger()", e);
			return false;
		}
		return true;
	}  
}
